﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;

namespace TTApp.Phone.Silverlight.Hexagons
{
    /// <summary>
    /// Chứa logic cho kiểu chơi game cổ điển, giống phiên bản trên web.
    /// </summary>
    public partial class ClassicGame : GameBase
    {
        #region //----------------------------- Class Private Fields --------------------------------------//
        private Hexagon _activeHexagon;
        protected Player _player1;
        protected Player _player2;
        #endregion

        #region //----------------------------- Class Public Constructors ---------------------------------//
        /// <summary>
        /// Khởi tạo 1 đối tượng ClassicGame mới.
        /// </summary>
        public ClassicGame()
        {
            InitializeComponent();

            Loaded += new RoutedEventHandler(OnLoaded);    
            _xmlDataFile = "/Assets/Data/ClassicMap.xml";

            //Load Sound
            soundController = new SoundController();
        }

        #endregion

        #region //----------------------------- Class CLR Properties --------------------------------------//
        /// <summary>
        /// Lấy hoặc gán đối tượng người chơi 1.
        /// </summary>
        public Player Player1
        {
            get
            {
                return _player1;
            }
            //set
            //{
            //    if (_isGameStarted)
            //    {
            //        throw new InvalidOperationException("Game đã bắt đầu, không thể thay đổi người chơi.");
            //    }

            //    _playerList.Remove(_player1);

            //    _player1 = value;
            //    _playerList.Add(_player1);
            //}
        }

        /// <summary>
        /// Lấy hoặc gán đối tượng người chơi 2.
        /// </summary>
        public Player Player2
        {
            get
            {
                return _player2;
            }
            //set
            //{
            //    if (_isGameStarted)
            //    {
            //        throw new InvalidOperationException("Game đã bắt đầu, không thể thay đổi người chơi.");
            //    }

            //    _playerList.Remove(_player2);


            //    _player2 = value;
            //    _playerList.Add(_player2);
            //}
        }
        #endregion

        #region //----------------------------- Private Event Handlers ------------------------------------//
        /// <summary>
        /// Bây giờ thì mới có _board.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnLoaded(object sender, RoutedEventArgs args)
        {
            _player1 = _playerList[0];
            _player2 = _playerList[1];
        }

        /// <summary>
        /// Xử lý sự kiện khi 1 hexagon chuẩn bị được xuất hiện trên màn hình.
        /// </summary>
        private void OnSpawnedHexagonAppearing(object sender, EventArgs args)
        {
            // Bỏ đăng kí để tránh đăng kí nhiều lần.
            Hexagon hexagon = sender as Hexagon;
            hexagon.Appearing -= OnSpawnedHexagonAppearing;
        }

        /// <summary>
        /// Xử lý công việc khi 1 hexagon vừa mới xuất hiện.
        /// </summary>
        private void OnSpawnedHexagonAppeared(object sender, EventArgs args)
        {
            // Bỏ đăng kí để tránh bị đăng kí nhiều lần.
            Hexagon hexagon = sender as Hexagon;
            hexagon.Appeared -= OnSpawnedHexagonAppeared;

            CheckNewLocation(hexagon);

            OnTurnFinished(EventArgs.Empty);
        }

        /// <summary>
        /// Phát âm thanh cho việc nhảy.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnJumpedHexagonAppearing(object sender, EventArgs args)
        {
            // Bỏ đăng kí để tránh bị đăng kí nhiều lần.
            Hexagon hexagon = sender as Hexagon;
            hexagon.Appearing -= OnJumpedHexagonAppearing;

            // Bây giờ mới phát âm thanh thì hợp lý hơn.
            soundController.PlayHexagonJump();
        }

        /// <summary>
        /// Kiểm tra khu vực xung quanh xem có ăn được quân nào không, chuyển lượt.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnJumpedHexagonAppeared(object sender, EventArgs args)
        {
            // Bỏ đăng kí để tránh bị đăng kí nhiều lần.
            Hexagon hexagon = sender as Hexagon;
            hexagon.Appeared -= OnJumpedHexagonAppeared;

            CheckNewLocation(hexagon);

            OnTurnFinished(EventArgs.Empty);
        }
        #endregion

        #region //----------------------------- Class Public Methods --------------------------------------//
        /// <summary>
        /// Lấy Player với id tương ứng. Id là 1 hoặc 2.
        /// </summary>
        /// <param name="id">1 hoặc 2 tương ứng với Player1 hoặc Player2.</param>
        /// <returns>Người chơi 1 hoặc người chơi 2 trong game.</returns>
        public override Player GetPlayer(int id)
        {
            if (id == 1)
            {
                return _player1;
            }
            else if (id == 2)
            {
                return _player2;
            }
            else
            {
                throw new ArgumentOutOfRangeException("id", "Id phải là 1 hoặc 2.");
            }
        }
        #endregion

        #region//----------------------------- Class Protected Methods -----------------------------------//
        /// <summary>
        /// Sinh thêm 1 Hexagon mới ở vị trí của HexagonSlot, sở hữu bởi owner.
        /// </summary>
        /// <param name="owner">Người chơi sở hữu hexagon này.</param>
        /// <param name="spawnner">Hexagon sinh ra Hexagon khác.</param>
        /// <param name="target">HexagonSlot chứa hexagon mới được sinh.</param>
        protected void SpawnHexagon(Hexagon spawnner, HexagonSlot target)
        {
            // Kích hoạt Hexagon này nếu nó chưa được kích hoạt (gọi bởi AI).
            if (!spawnner.IsActive)
            {
                spawnner.Active();
            }

            // Tạo hexagon mới.
            Hexagon hexagon = new Hexagon();
            spawnner.Owner.Seize(hexagon);

            // Đăng kí sự kiện tap cho hexagon này.
            RegisterEvent(hexagon);
            hexagon.Appearing += new EventHandler(OnSpawnedHexagonAppearing);
            hexagon.Appeared += new EventHandler(OnSpawnedHexagonAppeared);

            // Bắt đầu animation sinh đẻ :|
            spawnner.StartSpawnAnimation(hexagon, target);
            soundController.PlayHexagonSpawn();

            // Hexagon đang được kích hoạt sẽ bị bất hoạt ngay sau animation phía trên.
            // _activeHexgon có thể null nếu hàm này được gọi bởi AI
            _activeHexagon = null;
        }

        /// <summary>
        /// Cho Hexagon 'toJump' nhảy đến 'hexagonSlot'.
        /// </summary>
        /// <param name="toJump">Hexagon sẽ nhảy.</param>
        /// <param name="target">Đích nhảy của Hexagon.</param>
        protected void JumpToHexagonSlot(Hexagon toJump, HexagonSlot target)
        {
            if (!toJump.IsActive)
            {
                toJump.Active();
            }

            toJump.Appearing += new EventHandler(OnJumpedHexagonAppearing);
            toJump.Appeared += new EventHandler(OnJumpedHexagonAppeared);
            toJump.StartJumpAnimation(target);

            // Việc deactive Hexagon sẽ được thực hiện ngay sau khi Hexagon biến mất.
            _activeHexagon = null;
        }
        #endregion

        #region //----------------------------- Class Private Methods -------------------------------------//
        /// <summary>
        /// Kiểm tra tại vị trí xuất hiện mới của Hexagon có thể ăn Hexagon nào của người chơi
        /// khác hay không.
        /// </summary>
        /// <param name="hexagon">Hexagon vừa xuất hiện ở vị trí mới.</param>
        private void CheckNewLocation(Hexagon hexagon)
        {
            List<Hexagon> neighbours = hexagon.GetNeighbours();
            foreach (Hexagon neighbour in neighbours)
            {
                if (neighbour != null && !_currentPlayer.IsOwn(neighbour))
                {
                    _currentPlayer.Seize(neighbour);
                }
            }
        }

        #endregion

        #region //----------------------------- Overridden Methods ----------------------------------------//
        /// <summary>
        /// Xử lý sự kiện chạm vào Hexagon.
        /// </summary>
        protected override void OnHexagonTap(Hexagon tappedHexagon)
        {
            // Nếu hexagon vừa được chạm thuộc quyền sở hữu của người chơi hiện tại.
            if (_currentPlayer.IsOwn(tappedHexagon))
            {
                soundController.PlayHexagonSelect();
                // Nếu nó là hexagon đang được kích hoạt thì bỏ kích hoạt nó
                if (tappedHexagon == _activeHexagon)
                {
                    tappedHexagon.Deactive();
                    _activeHexagon = null;
                }
                // Nếu nó là hexagon khác thì bỏ kích hoạt hexagon cũ và kích hoạt hexagon mới.
                else
                {
                    if (_activeHexagon != null)
                    {
                        _activeHexagon.Deactive();
                    }
                    tappedHexagon.Active();
                    _activeHexagon = tappedHexagon;
                }
            }
            else
            {
                soundController.PlayButtonClick(false);
            }
        }

        /// <summary>
        /// Xử lý sự kiện chạm vào HexagonSlot.
        /// </summary>
        protected override void OnHexagonSlotTap(HexagonSlot tappedSlot)
        {
            // Nếu có hexagon nào đó đang active thì thực hiện tiếp
            if (_activeHexagon != null)
            {
                //Hàng xóm cấp 1 -> sinh thêm Hexagon mới, cộng điểm cho người chơi.
                if (tappedSlot.IsNeighbourWith(_activeHexagon, 1))
                {
                    SpawnHexagon(_activeHexagon, tappedSlot);
                }
                else if (tappedSlot.IsNeighbourWith(_activeHexagon, 2))
                {
                    JumpToHexagonSlot(_activeHexagon, tappedSlot);
                }
                else
                {
                    _activeHexagon.Deactive();
                    _activeHexagon = null;
                }
            }
        }

        /// <summary>
        /// Kiểm tra trạng thái hiện tại của game, đã kết thúc hay chưa, có người chiến thắng hay hòa.
        /// </summary>
        /// <returns></returns>
        public override GameState CheckGameState()
        {
            // Người chơi hiện tại vẫn có thể đi tiếp, tiếp tục cuộc chơi.
            if (_currentPlayer.CanMove())
            {
                return GameState.NotFinished;
            }

            // Bằng điểm nhau, hòa.
            if (_player1.Score == _player2.Score)
            {
                return GameState.Draw;
            }

            // Không bằng điểm, có người chiến thắng.
            return GameState.Win;
        }

        /// <summary>
        /// Lấy người chiến thắng của ván chơi vừa xong. Trả về null nếu game chưa kết thúc hoặc ở trạng thái hòa.
        /// </summary>
        /// <returns> Nếu CheckGameState() trả về:
        ///     - Win: người chơi chiến thắng.
        ///     - Draw / NotFinised: null.
        /// </returns>
        /// <remarks>Nên gọi CheckGameState() trước, nếu nó trả về GameState.Win thì mới
        ///     gọi hàm này để lấy người chơi chiến thắng.</remarks>
        public override Player GetVictoryPlayer()
        {
            GameState state = CheckGameState();

            if (state == GameState.NotFinished || state == GameState.Draw)
            {
                return null;
            }

            if (_player1.Score > _player2.Score)
            {
                return _player1;
            }
            else
            {
                return _player2;
            }
        }

        /// <summary>
        /// Xử lý ngừng kích hoạt Hexagon.
        /// </summary>
        protected override void OnBoardTap()
        {
            if (_activeHexagon != null)
            {
                _activeHexagon.Deactive();
                _activeHexagon = null;
            }
        }

        /// <summary>
        /// Bật nhạc nền.
        /// </summary>
        /// <param name="args"></param>
        protected override void OnGameStarting(EventArgs args)
        {
            if (!soundController.IsMute)
                soundController.PlayBackgoundSound();

            base.OnGameStarting(args);
        }

        protected override void OnGameEnded(EventArgs args)
        {
            //Tắt Sound nền, bật sound kết thúc
            soundController.StopBackgroundSound();
            soundController.PlayEndGame();

            base.OnGameEnded(args);
        }
        #endregion
    }
}